﻿/*************************** Copyright *****************************\
 * Copyright 2011 Sendine.com - http://www.sendine.com/
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
\*******************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace Sendine.Web.Route.Cfg
{
    /// <summary>
    /// route section [domain]
    /// </summary>
    public class RouterDomain : List<RouterRule>, IXmlSerializable
    {
        public const string cRouterDomain = "domain";
        public const string cRouterDomainName = "name";
        public const string cRouterDomainBound = "bound";
        public const string cRouterDomainPort = "port";

        private string name;
        private List<string> bound;
        private List<string> port;


        public RouterDomain(string name, string bound, string port)
        {
            this.Name = name;
            this.Bound = bound;
            this.Port =  port;
        }
        public RouterDomain() : this(string.Empty, "*", "*") { }

        /// <summary>
        /// route key
        /// </summary>
        public string Name
        { 
            get { return name; } 
            set { name = value; }
        }

        /// <summary>
        /// bind domain ,default value [*]
        /// </summary>
        public string Bound
        {
            get { return string.Join(";", bound.ToArray()); }
            set
            {
                bound = new List<string>();
                if (string.IsNullOrEmpty(value))
                {
                    bound.Add("*");
                }
                else
                {
                    bound.AddRange(value.Split(';'));
                }
            }
        }

        /// <summary>
        /// effect port ,default value [*]
        /// </summary>
        public string Port
        {
            get { return string.Join(";", port.ToArray()); }
            set
            {
                port = new List<string>();
                if (string.IsNullOrEmpty(value))
                {
                    port.Add("*");
                }
                else
                {
                    port.AddRange(value.Split(';'));
                }
            }
        }

        /// <summary>
        /// list of rules
        /// </summary>
        public RouterRule[] Rules
        {
            get
            {
                return this.ToArray();
            }
        }

        /// <summary>
        /// check whether match regex.
        /// </summary>
        /// <param name="hostname">host</param>
        /// <param name="port">port</param>
        /// <returns></returns>
        public bool IsMatch(string hostname, string port)
        {
            foreach (string host in bound)
            {
                if (host.ToLower() == hostname.ToLower())
                {
                    if (this.port.Contains("*"))
                        return true;
                    foreach (string subport in this.port)
                    {
                        if (subport.ToLower() == port.ToLower())
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        #region IXmlSerializable
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 从Xml文档中序列化
        /// </summary>
        /// <param name="reader"></param>
        public void ReadXml(XmlReader reader)
        {
            if (reader.ReadToFollowing(cRouterDomain))
            {
                XmlDocument document = new XmlDocument();
                document.Load(reader.ReadSubtree());
                XmlElement elHmData = document.DocumentElement;
                this.Name = elHmData.GetAttribute(cRouterDomainName);
                this.Bound = elHmData.GetAttribute(cRouterDomainName);
                this.Port = elHmData.GetAttribute(cRouterDomainPort);
                foreach (XmlElement elResult in elHmData.ChildNodes)
                {
                    if (elResult.Name.ToLower() == RouterRule.cRouterRule)
                    {
                        RouterRule rule = new RouterRule(elResult.GetAttribute(RouterRule.cRuleRegex),
                                                         elResult.GetAttribute(RouterRule.cRuleTarget),
                                                         elResult.GetAttribute(RouterRule.cRuleValidator),
                                                         elResult.GetAttribute(RouterRule.cAssembly),
                                                         Name,
                                                         elResult.GetAttribute(RouterRule.cReplace),
                                                         elResult.GetAttribute(RouterRule.cTrim));
                        this.Add(rule);
                    }
                }
            }
        }

        /// <summary>
        /// 转化为XML文档
        /// </summary>
        /// <param name="writer"></param>
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement(cRouterDomain);
            writer.WriteAttributeString(cRouterDomainName, Name);
            writer.WriteAttributeString(cRouterDomainBound, Bound);
            writer.WriteAttributeString(cRouterDomainPort, Port);
            foreach (RouterRule rule in this)
            {
                writer.WriteStartElement(RouterRule.cRouterRule);

                if (!string.IsNullOrEmpty(rule.Regex))
                    writer.WriteAttributeString(RouterRule.cRuleRegex, rule.Regex);

                if (!string.IsNullOrEmpty(rule.Target))
                    writer.WriteAttributeString(RouterRule.cRuleTarget, rule.Target);

                if (!string.IsNullOrEmpty(rule.ReplacementString))
                    writer.WriteAttributeString(RouterRule.cReplace, rule.ReplacementString);

                if (!string.IsNullOrEmpty(rule.Trim))
                    writer.WriteAttributeString(RouterRule.cTrim, rule.Trim);

                if (!string.IsNullOrEmpty(rule.ValidatorName))
                    writer.WriteAttributeString(RouterRule.cRuleValidator, rule.ValidatorName);

                if (!string.IsNullOrEmpty(rule.AssemblyName))
                    writer.WriteAttributeString(RouterRule.cAssembly, rule.AssemblyName);

                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        #endregion
    }
}